﻿using System.Collections.Generic;
using System.IO;
using FitNesseRunner.Model;

namespace FitNesseRunner
{
	class Program
	{
		static void Main(string[] args)
		{
			var path = args[0];
			var executionListProvider = new ExecutionListProvider<Folder>(new Folder.Manager());
			var folderTypeResolver = new FolderTypeResolver();
			
			var folder = new Folder(path, folderTypeResolver);

			var reflectionProviderFactory = new ReflectionProviderFactory();
			var rootContext = new Context(path, reflectionProviderFactory);
			RunTest(executionListProvider.GetRoot(folder).Path, rootContext);

			var imports = new HashSet<string>();
			foreach (var testFolder in executionListProvider.Suite(folder))
			{
				var context = new Context(testFolder.Folder.Path, imports, reflectionProviderFactory);
				if (testFolder.SetUpFolder != null)
					RunTest(testFolder.SetUpFolder.Path, context);

				RunTest(testFolder.Folder.Path, context);

				if (testFolder.TearDownFolder != null)
					RunTest(testFolder.TearDownFolder.Path, context);
			}
		}

		private static void RunTest(string path, Context context)
		{
			var reporter = new Reporter();
			reporter.RunTest(path);

			var contentPath = Path.Combine(path, "Content.txt");
			var content = File.ReadAllLines(contentPath);
			
			var pageParser = CreatePageParser(context, reporter);
			var lines = new VariablesHandler(content, new AssemblyLoader()).GetAllLines();
			pageParser.Parse(lines);
		}

		private static PageParser CreatePageParser(IContext context, Reporter reporter)
		{
			var directiveHandlers = new IDirectiveHandler[0];
			var tableHandlers = new ITableHandler[]
				{
					new ImportTableHandler(context),
					new ScriptTableHandler(reporter, context),
					new CommentTableHandler(),
					new QueryTableHandler(reporter, context)
				};
			var defaultHandler = new DecisionTableHandler(reporter, context.ReflectionProvider);
			var pageObserver = new PageHandlerDispatcher(directiveHandlers, tableHandlers, defaultHandler, reporter);
			return new PageParser(pageObserver);
		}
	}

	public enum FolderType
	{
		Suite,
		Test,
		None
	}
}
